/**
 * @brief PDF文件阅读器.
 */
#ifndef CPDFREADER_H
#define CPDFREADER_H

#include <vector>
#include <auto_ptr.h>

#include <wx/wx.h>
#include <wx/scrolwin.h>

#include <poppler/cpp/poppler-document.h>
#include <poppler/cpp/poppler-page.h>
#include <poppler/cpp/poppler-image.h>
#include <poppler/cpp/poppler-page-renderer.h>
#include <poppler/cpp/poppler-page-transition.h>

class CPdfCanvas;

class CPdfReader : public wxScrolledWindow
{
    DECLARE_EVENT_TABLE()
public:
    typedef std::vector< CPdfCanvas* >     Pages;
    enum en_error_code{
        ERR_NO_FILE_NAME    = -1000,
        ERR_OPEN_PDF_FILE,
        ERR_CREATE_PAGE,
        OK = 0
    };
public:
    CPdfReader();
    CPdfReader( wxWindow* parent ,
               wxWindowID id = -1,
               const wxPoint& pos = wxDefaultPosition,
               const wxSize& size = wxDefaultSize,
               long style = wxHSCROLL | wxVSCROLL,
               const wxString& name = _("poppler window"));
    virtual ~CPdfReader();

    bool Create(wxWindow* parent ,
               wxWindowID id = -1,
               const wxPoint& pos = wxDefaultPosition,
               const wxSize& size = wxDefaultSize,
               long style = wxHSCROLL | wxVSCROLL,
               const wxString& name = _("poppler window"));
    /**
        @brief 打开文件
        @param file , 文件名称。字符串类型
        @return 成功返回0，否则返回错误代码
    */
    int Open( const std::string& file , double scale = 1.0 );
    int Open( const wxString& file , double scale = 1.0 );
    /**
    * @brief 缩放页面
    * @param double scale , 缩放比例
    * @param p_i , 页面索引
    * @return , 成功返回0 ，否则返回错误代码
    */
    int Scale( double scale );

    int Scale( int p_i , double scale );

    /**
    * @brief 旋转页面。页面只有四种角度，竖直，向左，向右，向下
    * @param angle
    * @retval 成功返回0，否则返回错误代码
    */
    int Rotate( poppler::rotation_enum  angle );
    int Rotate( int p_i , poppler::rotation_enum angle );
    /**
     * @brief 设定不同页面的之间间距
     * @param h_gap , 水平间距；v_gap，竖直间距
     * @retval
    */
    void SetPageGap( int h_gap , int v_gap );
    /**
    * @brief 获取页面数量
    */
    int GetCount();
    /**
    * @brief 实际的界面绘制函数
    */
    virtual void OnDraw( wxDC& dc );
    /**
    @brief 切换当前页面。next到下一页，pre到上一页；goto到指定页面
    @param index , 页码
    */
    void NextPage();

    void PrePage();

    void GotoPage( int index );

    int GetCurrentPage(){ return m_current_page; }
    void OnMouseRightUp( wxMouseEvent& evt );
    poppler::rotation_enum GetCurrentOrient(){ return m_orient; }

    void CloseFile();

    void OnScroll( wxScrollWinEvent& evt );
    void OnScrollLineUp( wxScrollWinEvent& evt );
    void OnScrollLineDown( wxScrollWinEvent& evt );
    void OnScrollTop( wxScrollWinEvent& evt );
    void OnScrollBottom( wxScrollWinEvent& evt );
    void OnScrollThumb( wxScrollWinEvent& evt );
private:
    /*这里处理页面的相关操作，比如处理滚动时间的响应*/
    /**
    * @brief 绘制指定页面
    * @param int index ， 页面索引
    */
    int draw_page( int index );
    /**
    * @brief 计算页面显示的左上角坐标
    * @param page，pdf页面
    * @param pos ，显示的坐标
    * @retval , 成功返回0，否则返回错误代码
    */
    int get_page_pos( wxPoint& pos , poppler::page *page );
    /**
    * @brief 获取页面大小和位置
    * @return
    * @param wxRect& rect ,
    & @param poppler::page *page
    */
    int get_page_rect( wxRect& rect , poppler::page *page );
    /**
    * @brief 获取页面大小
    * @param wxPoint& size
    * @param poppler::page *page
    * @retval 成功返回0，否则返回错误代码
    */
    int get_page_size( wxPoint& size , poppler::page *page );
private:
    Pages                   m_pages;            //阅读器的页面

    int                     m_h_gap;            //页面的水平间隙
    int                     m_v_gap;            //页面的垂直间隙

    int                     m_col_count;        //列数量

    wxColour                m_bk_color;         //窗口的背景色

    int                     m_current_page;     //当前页面
    bool                    m_is_need_render[5];   //是否需要重新绘制
    int                     m_page_count;       //页面总数
    int                     m_page_rendered_up;    //已经渲染的页面的最大编号
    int                     m_page_rendered_low;
    int                     m_current_pos;      //当前页面的最高可见位置
    int                     m_page_h;           //页面高度
    int                     m_page_w;           //页面宽度
    float                   m_show_page;        //显示的页面的数量

    poppler::rectf          m_page_org_size;    //页面的原始尺寸
    double                  m_x_res;            //X方向分辨率
    double                  m_y_res;            //Y方向分辨率
    poppler::document       *p_doc;             //PDF文件
    poppler::rotation_enum  m_orient;           //当前页面方向
    friend class CPdfCanvas;
};

#endif // CPDFREADER_H
